#include "./recv_service.h"
#include "../driver/cmd_uart.h"
#include "../conn/proto_handler.h"
#include "../conn/message.h"
#include "../task/handler_task.h"
#include "./config.h"

namespace service {

using namespace driver;
using namespace conn;
using namespace utils;
using namespace task;

class CmdHandler : public ProtoHandler<CmdHandler, 512> {

public:
    static void do_query(const Message &msg) {
        uint8_t cmd = msg.query_cmd();
    
        switch (cmd) {
            case query::ARGS: query_arg();
        }
    }

    static void query_arg() {
        uint8_t draw_timeout = config->draw_timeout / 1000 / 60;
        uint8_t heat_timeout = config->heat_timeout / 1000 / 60;
        cmdUart->write_result(query::ARGS, 
            draw_timeout,
            heat_timeout,
            config->steam_temp,
            config->steam_kpa,
            config->flow1000_count,
            config->pump_ml_ms,
            config->door_lock_adc
        );
    }

    void do_req(const Message &msg) {
        if (!m_session_flag) {
            return;
        }
        m_session_flag = false;
        handlerTask->post(msg);
    }

    static bool poll(ByteView &bw, uint32_t timeout = osWaitForever) {
        return cmdUart->poll(bw, timeout);
    }

    void proto_ready(const uint8_t *buf, uint8_t len) {
        Message msg(buf, len);

        switch (msg.type()) {

            case type::ACK: cmdUart->on_ack(); break;

            case type::QUERY: do_query(msg); break;

            case type::SESSION: 
                m_session_flag = true;
                cmdUart->write_ack(msg.seq());
            break;

            case type::REQ:
                cmdUart->write_ack(msg.seq());
                do_req(msg);
            break;

            
        }
    }

private:
    bool m_session_flag = false;
};

static CmdHandler cmdHandler;

void recv_loop() {
    cmdHandler.exec();
}

}
